﻿#region [===== Using =====]
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Xml.Serialization;
using System.Globalization;
using Microsoft.SharePoint.Workflow;
#endregion

namespace TPG.SharePoint.Workflow
{
  /// <summary>
  /// Support class for serializing and deserializing workflow data such
  /// as association or task data.
  /// </summary>
  public static class WorkflowDataSerializer
  {
    #region [===== Public methods =====]
    /// <summary>
    /// Serializes an object using the <see cref="BinaryFormatter" /> 
    /// into a Base64 encoded string.
    /// </summary>
    /// <param name="data">The data to serialize.</param>
    /// <typeparam name="TData">The type of data to process.</typeparam>
    /// <returns>A Base64 encoded string containing serialized 
    /// data.</returns>
    public static string SerializeToBase64String<TData>(TData data)
    {
      using (MemoryStream ms = new MemoryStream())
      {
        BinaryFormatter formatter = new BinaryFormatter();
        formatter.Serialize(ms, data);
        return Convert.ToBase64String(ms.ToArray());
      }
    }

    /// <summary>
    /// Deserializes an object from a Base64 encoded string 
    /// using the <see cref="BinaryFormatter" />.
    /// </summary>
    /// <param name="data">The Base64 encoded data to deserialize.</param>
    /// <typeparam name="TData">The type of data to process.</typeparam>
    /// <returns>The deserialized object.</returns>
    public static TData DeserializeFromBase64String<TData>(string data)
    {
      return (TData)DeserializeFromBase64String(data);
    }

    /// <summary>
    /// Deserializes an object from a Base64 encoded string 
    /// using the <see cref="BinaryFormatter" />.
    /// </summary>
    /// <param name="data">The Base64 encoded data to deserialize.</param>
    /// <returns>The deserialized object.</returns>
    public static object DeserializeFromBase64String(string data)
    {
      using (MemoryStream ms = new MemoryStream())
      {
        byte[] content = Convert.FromBase64String(data);
        ms.Write(content, 0, content.Length);
        ms.Position = 0;
        BinaryFormatter formatter = new BinaryFormatter();
        return formatter.Deserialize(ms);
      }
    }

    /// <summary>
    /// Serializes an object using the <see cref="XmlSerializer" /> 
    /// into an XML string.
    /// </summary>
    /// <param name="data">The data to serialize.</param>
    /// <typeparam name="TData">The type of data to process.</typeparam>
    /// <returns>An XML string containing serialized 
    /// data.</returns>
    public static string SerializeToXmlString<TData>(TData data)
    {
      StringBuilder serializedData = new StringBuilder();
      using (StringWriter writer = new StringWriter(serializedData, CultureInfo.InvariantCulture))
      {
        XmlSerializer serializer = new XmlSerializer(typeof(TData));
        serializer.Serialize(writer, data);
      }
      return serializedData.ToString();
    }


    /// <summary>
    /// Deserializes an object from an XML string 
    /// using the <see cref="XmlSerializer" />.
    /// </summary>
    /// <param name="data">The XML data to deserialize.</param>
    /// <typeparam name="TData">The type of data to process.</typeparam>
    /// <returns>The deserialized object.</returns>        
    public static TData DeserializeFromXmlString<TData>(string data)
    {
      return (TData)DeserializeFromXmlString(data, typeof(TData));
    }

    /// <summary>
    /// Deserializes an object from an XML string 
    /// using the <see cref="XmlSerializer" />.
    /// </summary>
    /// <param name="data">The XML data to deserialize.</param>
    /// <returns>The deserialized object.</returns>        
    public static object DeserializeFromXmlString(string data, Type dataType)
    {
      using (StringReader reader = new StringReader(data))
      {
        XmlSerializer serializer = new XmlSerializer(dataType);
        return serializer.Deserialize(reader);
      }
    }
    #endregion
  }
}
